home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / PASCAL / ALLSWAGS.ZIP / SWAGG-M.ZIP / MISC.SWG / 0192_Card Game of Spite & Malice.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-11-29  |  58.6 KB  |  1,934 lines

  1. {_____________________________________________________________________________
  2. |  Filename: CODE.PAS
  3. |     Title: Spite & Malice
  4. |  Written By: Benjamin Arnoldy and Raechel Kula
  5. |_____________________________________________________________________________
  6. |  Contents:
  7. |    The procedures: Deal, WhoseTurn, PickupCards, Decision, GetMove,
  8. |                    CheckMove, MoveCard
  9. |    Oject: Pile
  10. |_____________________________________________________________________________
  11. |  Synopsis:
  12. |    This program allows the user to select either another person, or the
  13.      computer as the opponent, then play the opponent in the card game
  14. |    Spite & Malice.  The interface is textual.
  15. |_____________________________________________________________________________
  16. |  Description:
  17. |    No references at this time.
  18. |_____________________________________________________________________________
  19. |  Environment:
  20. |    TurboPASCAL for the PC.
  21. |_____________________________________________________________________________
  22. |  Version History:
  23. |
  24. |  Version 5.1 -- May 8, 1996
  25. |              Raechel Kula & Benjamin Arnoldy
  26. |              Improved interface and Decision.
  27. |
  28. |  Version 5.0 -- May 7, 1996
  29. |              Raechel Kula & Benjamin Arnoldy
  30. |              Code is cleaned up and ready for presentation.
  31. |
  32. |  Version 4.3 -- May 6, 1996
  33. |               Raechel Kula & Benjamin Arnoldy
  34. |               Additional testing, more tinkering with weights.
  35. |
  36. |  Version 4.2 -- May 5, 1996
  37. |               Raechel Kula & Benjamin Arnoldy
  38. |               Added provisions in decision for jokers.
  39. |
  40. |  Version 4.1 -- May 4, 1996
  41. |                Raechel Kula & Benjamin Arnoldy
  42. |                Testing and tinkering with weights to make
  43. |                the computer a better opponent.
  44. |
  45. |  Version 4.0 -- May 3, 1996
  46. |                Raechel Kula & Benjamin Arnoldy
  47. |                An "operable" Decision procedure is
  48. |                in place.
  49. |
  50. |  Version 3.1 -- May 2, 1996
  51. |                Raechel Kula & Benjamin Arnoldy
  52. |                Various Embellishments to make it an operable
  53. |                2 player game (e.g. end of game stuff).
  54. |
  55. |  Version 3.0 -- May 1, 1996
  56. |                 Raechel Kula & Benjamin Arnoldy
  57. |                 Ascii Graphical Interface is instituted.
  58. |
  59. |  Version 2.9 -- April 30, 1996
  60. |                 Raechel Kula & Benjamin Arnoldy
  61. |                 Small display functions (CardString) coded.
  62. |
  63. |  Version 2.2 -- April 28, 1996
  64. |                  Raechel Kula & Benjamin Arnoldy
  65. |                  CheckMove procedure ironed out.
  66. |
  67. |   Version 2.1 -- April 26, 1996
  68. |                  Raechel Kula & Benjamin Arnoldy
  69. |                  Basic Main Program Procedures Modified to fit with new
  70. |                  object structure.
  71. |
  72. |   Version 2.0 -- April 25, 1996
  73. |                  Raechel Kula & Benjamin Arnoldy
  74. |                   Object Pile Coded.
  75. |
  76. |    MidApril -- Meeting with Prof Squier & Subsequent Major Rethinking
  77. |
  78. |    Version 1.1 -- Apr. 7, 1996
  79. |                   Raechel Kula & Benjamin Arnoldy
  80. |                     Pieces of Decision and CheckMove procedures are
  81. |                     completed.
  82. |
  83. |    Version 1.0 -- Mar. 29, 1996
  84. |                   Raechel Kula & Benjamin Arnoldy
  85. |                     WhoseTurn, PickupCards, MoveCard procedures are coded.
  86. |                     The code successfully compiles.
  87. |
  88. |    Version 0.2 -- Mar. 12, 1996
  89. |                   Raechel Kula & Benjamin Arnoldy
  90. |                     Deal and GetMove procedures are coded.
  91. |
  92. |    Version 0.2 -- Mar. 5, 1996
  93. |                   Raechel Kula & Benjamin Arnoldy
  94. |                     GetValue and GetPlace procedures are coded.
  95. |
  96. |    Version 0.1 -- Feb. 30, 1996
  97. |                   Raechel Kula & Benjamin Arnoldy
  98. |                     Main Program and Stubs
  99. |    Version 0.0
  100. |____________________________________________________________________________}
  101.  
  102. program SpiteMalice;
  103.  
  104. uses CRT;
  105.  
  106. {=============================================================================
  107.                                    CONSTANTS
  108. =============================================================================}
  109.  
  110. const DRAWPILE_MAX = 108;
  111.       HAND_MAX = 6;
  112.       SCOREPILE_MAX = 14;
  113.       DISCARDPILE_MAX = 108;
  114.       ACEPILE_MAX = 13;
  115.       TRASHPILE_MAX = 108;
  116.       MAXSIZE = 108;
  117.       NULL = -1;
  118.  
  119. {=============================================================================
  120.                                      TYPES
  121. =============================================================================}
  122.  
  123. type CardVal_t = integer;
  124.      Pos_t = integer;
  125.      CardArray_t = array [1..108] of CardVal_t;
  126.      CardValTable_t = array [1..26] of CardVal_t;
  127.      choiceTable_t = array [1..26, 1..19] of integer;
  128.  
  129. {=============================================================================
  130.                               OBJECT DECLARATION
  131. =============================================================================}
  132.  
  133. type Pile = object
  134.    {public}
  135.    procedure Init;
  136.    procedure RandomShuffle;
  137.    procedure PutOnTop (CardtoPutOn: CardVal_t);
  138.    function RemoveFromTop: CardVal_t;
  139.    function SeeRandom (Pos: Pos_t): CardVal_t;
  140.    function DeleteByValue (value : CardVal_t): CardVal_t;
  141.    function IsPresent (CardtoFind: CardVal_t): boolean;
  142.    function NumCards: integer;
  143.  
  144.    private
  145.  
  146.    data: CardArray_t;
  147.    top: Pos_t;  {top = slot with top card in it.}
  148.  
  149. end; {Object declaration}
  150.  
  151. {=============================================================================
  152.                          OBJECT DEPENEDENT TYPES
  153. =============================================================================}
  154.  
  155. Type pilepointer_t = ^Pile;
  156.      stack_t = array [1..26] of pilepointer_t;
  157.  
  158. {=============================================================================
  159.                                 GLOBAL VARIABLES
  160. =============================================================================}
  161.  
  162. var DrawPile: Pile;
  163.     PlayerHand: Pile;
  164.     ComputerHand: Pile;
  165.     PlayerScorePile: Pile;
  166.     ComputerScorePile: Pile;
  167.     PlayerDiscardPile1: Pile;
  168.     PlayerDiscardPile2: Pile;
  169.     PlayerDiscardPile3: Pile;
  170.     PlayerDiscardPile4: Pile;
  171.     ComputerDiscardPile1: Pile;
  172.     ComputerDiscardPile2: Pile;
  173.     ComputerDiscardPile3: Pile;
  174.     ComputerDiscardPile4: Pile;
  175.     AcePile1: Pile;
  176.     AcePile2: Pile;
  177.     AcePile3: Pile;
  178.     AcePile4: Pile;
  179.     TrashPile: Pile;
  180.     ComputerTurn: boolean;
  181.     Game: boolean;
  182.     Valid, Discard, DecisionDiscard: boolean;
  183.     From, Tto: integer;
  184.     PosTable : stack_t;
  185.     TopCardTable: CardValTable_t;
  186.     pos: integer;
  187.     Winner: string;
  188.     ChoiceRate: choiceTable_t;
  189.     AnotherGame: boolean;
  190.     TwoPlayer: boolean;
  191.     MustMove: boolean;
  192.  
  193. {=============================================================================
  194.                        OBJECT PROCEDURES & FUNCTIONS
  195. =============================================================================}
  196.  
  197. {____________________________________________________________________
  198. | Init
  199. |       Initializes a pile's array (data) and pointer (top)
  200. |___________________________________________________________________}
  201.  
  202. procedure Pile.Init;
  203.  
  204. var Count: integer;
  205.  
  206. begin
  207.    top := MAXSIZE + 1;
  208.    for Count := 1 to MAXSIZE do
  209.       Pile.PutOnTop (NULL);   {Stores NULL values in entire array.}
  210.    top := MAXSIZE + 1;
  211. end; {procedure Init}
  212.  
  213. {____________________________________________________________________
  214. | RandomShuffle
  215. |         Shuffles the cards in a pile.
  216. |___________________________________________________________________}
  217.  
  218. procedure Pile.RandomShuffle;
  219.  
  220. var ShuffleArray: Pile;  {Temporary Storage Pile}
  221.     Counter: Pos_t;
  222.     RandSlot: integer;
  223.     DeckSize: integer;
  224.     TopofDeck: Pos_t;
  225.  
  226. begin
  227.    DeckSize := DrawPile.NumCards;
  228.    TopofDeck := (MAXSIZE - DeckSize) + 1;
  229.    ShuffleArray.Init;   {Initializing ShuffleArray}
  230.    ShuffleArray.top := TopofDeck;
  231.    for Counter := 1 to DeckSize do begin
  232.       RandSlot := Random (DeckSize) + 1;  {'+1' due to Random range.}
  233.       While ShuffleArray.SeeRandom (RandSlot) <> NULL do
  234.          RandSlot := Random (DeckSize) + 1;
  235.       ShuffleArray.top := TopofDeck + Randslot;
  236.          {Set ShuffleArray's "top" pointer to slot beneath empty slot, so
  237.           that PutOnTop will put the card in the empty slot.}
  238.       ShuffleArray.PutOnTop (DrawPile.RemoveFromTop);
  239.       ShuffleArray.top := TopofDeck;
  240.    end; {for}
  241.    ShuffleArray.top := TopofDeck;
  242.       {Set ShuffleArray's "top" pointer to the top of the stack.}
  243.    for Counter := 1 to DeckSize do
  244.       DrawPile.PutOnTop (ShuffleArray.RemoveFromTop);
  245.    {Transfered shuffled ShuffleArray to DrawPile.}
  246. end; {Procedure RandomShuffle}
  247.  
  248. {____________________________________________________________________
  249. | PutOnTop
  250. |      Places a card value on the top of the pile.
  251. |
  252. |___________________________________________________________________}
  253.  
  254. procedure Pile.PutOnTop (CardtoPutOn: CardVal_t);
  255.  
  256. begin
  257.    top := top - 1; {Advance the top pointer to the empty slot above it.}
  258.    If top < 0 then begin
  259.       writeln ('ERROR. Array Overflow.');
  260.       HALT;
  261.       {Program is stopped if program attempts to a put a card on top of what
  262.        should be a full pile.  This should never never happen given that the
  263.        size of the pile arrays are the same size as the number of cards.}
  264.    end;
  265.    data [top] := CardtoPutOn;
  266. end; {procedure PutOnTop}
  267.  
  268. {____________________________________________________________________
  269. | RemoveFromTop
  270. |      Removes the top card from a pile and return the value of
  271. |      of the card.
  272. |___________________________________________________________________}
  273.  
  274. function Pile.RemoveFromTop: CardVal_t;
  275.  
  276. begin
  277.    RemoveFromTop := data [top];
  278.    data [top] := NULL;
  279.    top := top + 1; {Adjusts the top pointer so it points at the top card.}
  280. end; {Procedure RemoveFromTop}
  281.  
  282. {____________________________________________________________________
  283. | SeeRandom
  284. |      Allows the program to view the card value in any given
  285. |      position in a stack.
  286. |___________________________________________________________________}
  287.  
  288. function Pile.SeeRandom (pos: Pos_t): CardVal_t;
  289.  
  290. begin
  291.    SeeRandom := data [top + pos - 1];
  292.       {The "- 1" in the equation defines position 1 as the top card.}
  293.    if (top + pos - 1) > MAXSIZE then
  294.       SeeRandom := NULL;
  295.    {if the seek excedes the boundaries, a null value is returned.}
  296. end; {Procedure SeeRandom}
  297.  
  298. {____________________________________________________________________
  299. |  DeleteByValue
  300. |       Searches through a pile for a designated value, and "pulls"
  301. |       the card out, returning the card's value.  After the card is
  302. |       removed, the gap in the stack is filled in by readjusting the
  303. |       cards.
  304. |___________________________________________________________________}
  305.  
  306. function Pile.DeleteByValue (value : CardVal_t): CardVal_t;
  307.  
  308. var count:integer; hold : CardVal_t;
  309.  
  310. begin
  311.    count:=0;
  312.    Repeat
  313.       count :=count+1;
  314.    Until (data[count] = value);
  315.    hold := data[top];
  316.    data[top] := value;
  317.    data[count] := hold;
  318.    hold := Pile.RemoveFromTop;
  319. end; {Procedure DeleteByValue}
  320.  
  321. {____________________________________________________________________
  322. | IsPresent
  323. |      Searches through a pile, looking to see if a designated card
  324. |      value is present.
  325. |___________________________________________________________________}
  326.  
  327. function Pile.IsPresent (CardtoFind: CardVal_t): boolean;
  328.  
  329. var
  330.    ValuePresent: boolean;
  331.  
  332. begin
  333.    ValuePresent := FALSE;
  334.    while ((ValuePresent = FALSE) OR (top > MAXSIZE)) do begin
  335.       top := top + 1;
  336.       If data [top] = CardtoFind then
  337.          ValuePresent := TRUE;
  338.       end; {While}
  339.       If ValuePresent = FALSE then
  340.          IsPresent := FALSE
  341.       else
  342.          IsPresent := TRUE;
  343. end; {Function IsPresent}
  344.  
  345. {____________________________________________________________________
  346. |  NumCards
  347. |      Returns the number of cards in a pile.
  348. |___________________________________________________________________}
  349.  
  350. function Pile.NumCards: integer;
  351.  
  352. begin
  353.    NumCards := (MAXSIZE - top) + 1;
  354.       {The "+ 1" in the equation takes into account that the position of top
  355.        contains a card.}
  356. end; {function NumCards}
  357.  
  358. {============================================================================
  359.                                GENERAL FUNCTIONS
  360. ============================================================================}
  361.  
  362. {____________________________________________________________________
  363. |  CardValue
  364. |     Converts card value (4..111) to orderinal value.
  365. |     (0 = Joker, 1,2,3,...10,11 = JACK,...)
  366. |___________________________________________________________________}
  367.  
  368. function CardValue (Card: CardVal_t): integer;
  369.  
  370. begin
  371.    if Card = NULL then
  372.       CardValue := NULL
  373.    else
  374.       CardValue := Card DIV 8;
  375. end; {function CardValue}
  376.  
  377. {____________________________________________________________________
  378. |  CardString
  379. |     Converts a card value to a string, for representation on the
  380. |     screen.
  381. |___________________________________________________________________}
  382.  
  383. function CardString (Card: CardVal_t): string;
  384. var
  385.    Number: integer;
  386.    Output: string;
  387.  
  388. begin
  389.    Number := Card DIV 8;
  390.    if Card = NULL then Output := '' else
  391.    if Number = 0 then Output := 'JO' else
  392.    if Number = 1 then Output := 'AC' else
  393.    if Number = 2 then Output := '02' else
  394.    if Number = 3 then Output := '03' else
  395.    if Number = 4 then Output := '04' else
  396.    if Number = 5 then Output := '05' else
  397.    if Number = 6 then Output := '06' else
  398.    if Number = 7 then Output := '07' else
  399.    if Number = 8 then Output := '08' else
  400.    if Number = 9 then Output := '09' else
  401.    if Number = 10 then Output := '10' else
  402.    if Number = 11 then Output := 'JA' else
  403.    if Number = 12 then Output := 'QU' else
  404.    if Number = 13 then Output := 'KI' else
  405.    Output := 'ERROR';
  406.  
  407.    Number := Card MOD 4;
  408.    if Card = NULL then Output := '' else
  409.    if (Card DIV 8) = 0 then Output := Output + '!' else
  410.    if Number = 0 then Output := Output + chr(3) else
  411.    if Number = 1 then Output := Output + chr(4) else
  412.    if Number = 2 then Output := Output + chr(5) else
  413.    if Number = 3 then Output := Output + chr(6) else
  414.    Output := 'ERROR';
  415.  
  416.    CardString := Output;
  417.  
  418. end; {function CardSuit}
  419.  
  420. {___________________________________________________________________
  421. |  AceTopCard
  422. |     Due to the possibility of a joker on an ace pile, this
  423. |     function returns the ordinal value of the card on the top of
  424. |     an ace pile -- if there's a joker it is converted to its
  425. |     ordinal value within the pile.
  426. |___________________________________________________________________}
  427.  
  428. function AceTopCard (Number: integer): integer;
  429.  
  430. var position: integer;
  431.  
  432. begin
  433.    position := 1;
  434.    while (CardValue (PosTable [Number]^.SeeRandom (position)) = 0) do
  435.       position := position + 1;
  436.    AceTopCard := CardValue (PosTable [Number]^.SeeRandom (position)) +
  437.                  position - 1;
  438. end; {function AceTopCard}
  439.  
  440. {============================================================================
  441.                              MAIN PROGRAM PROCEDURES
  442.                    (Grouped with corresponding sub-procedures)
  443. ============================================================================}
  444.  
  445. {___________________________________________________________________
  446. |  Initialize
  447. |      Does all the Non-Object initialization.
  448. |__________________________________________________________________}
  449.  
  450. procedure Initialize;
  451.  
  452. var count:integer;
  453.  
  454. begin
  455.    Randomize;
  456.    DrawPile.Init;
  457.    PlayerHand.Init;
  458.    ComputerHand.Init;
  459.    PlayerScorePile.Init;
  460.    ComputerScorePile.Init;
  461.    PlayerDiscardPile1.Init;
  462.    PlayerDiscardPile2.Init;
  463.    PlayerDiscardPile3.Init;
  464.    PlayerDiscardPile4.Init;
  465.    ComputerDiscardPile1.Init;
  466.    ComputerDiscardPile2.Init;
  467.    ComputerDiscardPile3.Init;
  468.    ComputerDiscardPile4.Init;
  469.    AcePile1.Init;
  470.    AcePile2.Init;
  471.    AcePile3.Init;
  472.    AcePile4.Init;
  473.    TrashPile.Init;
  474.    Game := TRUE;
  475.  
  476.    {Set up Position Table}
  477.  
  478.    PosTable[1] := @PlayerHand;
  479.    PosTable[2] := @PlayerHand;
  480.    PosTable[3] := @PlayerHand;
  481.    PosTable[4] := @PlayerHand;
  482.    PosTable[5] := @PlayerHand;
  483.    PosTable[6] := @PlayerHand;
  484.    PosTable[7] := @PlayerScorePile;
  485.    PosTable[8] := @PlayerDiscardPile1;
  486.    PosTable[9] := @PlayerDiscardPile2;
  487.    PosTable[10] := @PlayerDiscardPile3;
  488.    PosTable[11] := @PlayerDiscardPile4;
  489.    PosTable[12] := @AcePile1;
  490.    PosTable[13] := @AcePile2;
  491.    PosTable[14] := @AcePile3;
  492.    PosTable[15] := @AcePile4;
  493.    PosTable[16] := @ComputerDiscardPile1;
  494.    PosTable[17] := @ComputerDiscardPile2;
  495.    PosTable[18] := @ComputerDiscardPile3;
  496.    PosTable[19] := @ComputerDiscardPile4;
  497.    PosTable[20] := @ComputerHand;
  498.    PosTable[21] := @ComputerHand;
  499.    PosTable[22] := @ComputerHand;
  500.    PosTable[23] := @ComputerHand;
  501.    PosTable[24] := @ComputerHand;
  502.    PosTable[25] := @ComputerHand;
  503.    PosTable[26] := @ComputerScorePile;
  504.  
  505. end; {procedure Initialize}
  506.  
  507. {___________________________________________________________________
  508. |  InitTable
  509. |     Refreshes the values for the TopCardTable, which stores the
  510. |     values of the top card in all 26 positions.
  511. |__________________________________________________________________}
  512.  
  513. procedure InitTable;
  514.  
  515. var count:integer;
  516.  
  517. begin
  518.    for count := 1 to 6 Do
  519.       TopCardTable[count] := PosTable[count]^.SeeRandom (count);
  520.    for count := 7 to 19 Do
  521.       TopCardTable[count] := PosTable[count]^.SeeRandom (1);
  522.    for count := 20 to 25 Do
  523.       TopCardTable[count] := PosTable[count]^.SeeRandom(count-19);
  524.    TopCardTable[26] := PosTable[26]^.SeeRandom(1);
  525. end; {procedure InitTable}
  526.  
  527. {___________________________________________________________________
  528. |  Deal
  529. |    Deals the cards at the beginning of each game and decides,
  530. |    based on the outcome of the deal, who will go first.
  531. |__________________________________________________________________}
  532.  
  533. procedure Deal;
  534.  
  535. var Card: CardVal_t;
  536.     Counter: integer;
  537.     PlayerScoreTop: CardVal_t;
  538.     ComputerScoreTop: CardVal_t;
  539.  
  540. begin
  541.    for Card := (1 +3) to (MAXSIZE +3) do
  542.       {Put 2 decks of cards in draw pile, +3 is necessary for the div and mod
  543.        to operate correctly.}
  544.       DrawPile.PutOnTop (Card);
  545.    DrawPile.RandomShuffle;  {Shuffle the draw pile.}
  546.    for Counter := 1 to 5 do begin {Deal the hands}
  547.       PlayerHand.PutOnTop (DrawPile.RemoveFromTop);
  548.       ComputerHand.PutOnTop (DrawPile.RemoveFromTop);
  549.    end; {for}
  550.    for Counter := 1 to 14 do begin {Deal the score piles}
  551.       PlayerScorePile.PutOnTop (DrawPile.RemoveFromTop);
  552.       ComputerScorePile.PutOnTop (DrawPile.RemoveFromTop);
  553.    end; {for}
  554.    PlayerDiscardPile1.PutOnTop (DrawPile.RemoveFromTop);
  555.    PlayerDiscardPile2.PutOnTop (DrawPile.RemoveFromTop);
  556.    PlayerDiscardPile3.PutOnTop (DrawPile.RemoveFromTop);
  557.    PlayerDiscardPile4.PutOnTop (DrawPile.RemoveFromTop);
  558.    ComputerDiscardPile1.PutOnTop (DrawPile.RemoveFromTop);
  559.    ComputerDiscardPile2.PutOnTop (DrawPile.RemoveFromTop);
  560.    ComputerDiscardPile3.PutOnTop (DrawPile.RemoveFromTop);
  561.    ComputerDiscardPile4.PutOnTop (DrawPile.RemoveFromTop);
  562.         {Decide whose turn it is.  ComputerTurn set to opposite, because
  563.          it will be reversed in upcoming WhoseTurn procedure.}
  564.    PlayerScoreTop := CardValue (PlayerScorePile.SeeRandom(1));
  565.    ComputerScoreTop := CardValue (ComputerScorePile.SeeRandom(1));
  566.  
  567.    if PlayerScoreTop = 0 then
  568.       ComputerTurn := FALSE
  569.    else if ComputerScoreTop = 0 then
  570.       ComputerTurn := TRUE
  571.    else if PlayerScoreTop = ComputerScoreTop then
  572.       ComputerTurn := FALSE
  573.    else if PlayerScoreTop > ComputerScoreTop then
  574.       ComputerTurn := TRUE
  575.    else
  576.       ComputerTurn := FALSE;
  577.  
  578. end; {Deal}
  579.  
  580. {___________________________________________________________________
  581. |  OutString
  582. |     One of the procedures involving the interface.
  583. |     This procedure receives x,y coordinates for a screen position
  584. |     and outputs a string starting at that position.
  585. |__________________________________________________________________}
  586.  
  587. procedure OutString (x,y: integer; toPrint: string);
  588.  
  589. begin
  590.    GotoXY (x,y);
  591.    write (toPrint);
  592. end; {procedure OutString}
  593.  
  594. {____________________________________________________________________
  595. |  ColorDim
  596. |     One of the procedures involving the interface.
  597. |     Sets colors for displaying things involving the player whose
  598. |     turn it is not (hence, they are dimmed.)
  599. |___________________________________________________________________}
  600.  
  601. procedure ColorDim;
  602.  
  603. begin
  604.    TextColor (LIGHTgray);
  605.    TextBackground (BLACK);
  606. end; {procedure ColorDim}
  607.  
  608. {___________________________________________________________________
  609. |  ColorCard
  610. |     One of the procedures involving the interface.
  611. |     Sets colors for displaying a card of the player whose turn it
  612. |     is.
  613. |___________________________________________________________________}
  614.  
  615. procedure ColorCard;
  616.  
  617. begin
  618.    TextColor (YELLOW);
  619.    TextBackGround (BLUE);
  620. end; {procedure ColorCard}
  621.  
  622. {____________________________________________________________________
  623. |  ColorFrame
  624. |     One of the procedures involving the interface.
  625. |     Sets colors for highlighting the section of the frame
  626. |     involving the player whose turn it is.
  627. |___________________________________________________________________}
  628.  
  629.  
  630. procedure ColorFrame;
  631.  
  632. begin
  633.    TextColor (YELLOW);
  634.    TextBackground (BLACK);
  635. end; {procedure ColorFrame}
  636.  
  637. {____________________________________________________________________
  638. |  ColorNormalText
  639. |     One of the procedures involving the interface.
  640. |     Sets colors for normal text and is also the colors which the
  641. |     game returns to upon exiting.
  642. |___________________________________________________________________}
  643.  
  644. procedure ColorNormalText;
  645.  
  646. begin
  647.    TextColor (WHITE);
  648.    TextBackground (BLACK);
  649. end; {procedure ColorNormalText}
  650.  
  651. {___________________________________________________________________
  652. |  ColorPosition
  653. |     One of the procedures involving the interface.
  654. |     Sets colors for the display of position indicators.
  655. |__________________________________________________________________}
  656.  
  657. procedure ColorPosition;
  658.  
  659. begin
  660.    TextColor (WHITE);
  661.    TextBackground (RED);
  662. end; {procedure ColorPosition}
  663.  
  664. {___________________________________________________________________
  665. |  TitleScreen
  666. |     Displays a title screen and asks whether the user would like
  667. |     a one-player or a two-player game.  Accompanying procedures are
  668. |     called by TitleScreen
  669. |__________________________________________________________________}
  670.  
  671.  
  672.  
  673. procedure Heart;
  674. begin
  675. TextColor (red);
  676. TextBackground (LightGray);
  677. write (char(3));
  678. end;
  679.  
  680. procedure Club;
  681. begin
  682. TextColor (black);
  683. TextBackground (LightGray);
  684. write (char(5));
  685. end;
  686.  
  687. procedure Diamond;
  688. begin
  689. TextColor (red);
  690. TextBackground (lightgray);
  691. write (char(4));
  692. end;
  693.  
  694. procedure Spade;
  695. begin
  696. TextColor (black);
  697. TextBackground (lightgray);
  698. write (char(6));
  699. end;
  700.  
  701. procedure SuitsCol (x, y, count: integer);
  702. var c :integer;
  703. begin
  704. c := 0;
  705. while (count > 0) Do begin
  706.  GotoXY (x, y+c*4);
  707.  Heart;
  708.  GotoXY (x, y+c*4+1);
  709.  Club;
  710.  GotoXY (x, y+c*4+2);
  711.  Diamond;
  712.  GotoXY (x, y+c*4+3);
  713.  Spade;
  714.  c := c + 1;
  715.  count := count - 1;
  716.  TextBackGround (black);
  717. end; {while loop}
  718. end; {SuitsCol}
  719.  
  720. procedure SuitsRow (x, y, count: integer);
  721. var c :integer;
  722. begin
  723. c := 0;
  724. while (count > 0) Do begin
  725.  GotoXY (x + (4*c), y);
  726.  Heart;
  727.  Club;
  728.  Diamond;
  729.  Spade;
  730.  c := c + 1;
  731.  count := count - 1;
  732.  TextBackground (black);
  733. end; {while loop}
  734. end; {SuitsRow}
  735.  
  736. procedure DrawTitleBox;
  737. Begin
  738. SuitsCol (25, 7, 2);
  739. SuitsRow (25, 7, 8);
  740. SuitsRow (25, 15, 8);
  741. SuitsCol (57, 7, 2);
  742. GotoXY (57, 15);
  743. Heart;
  744. end; {DrawTitleBox}
  745.  
  746. procedure Title;
  747.  begin
  748.   TextColor (white);
  749.   TextBackground (black);
  750.   OutString (28, 9, 'Welcome to Spite & Malice!');
  751.  end;
  752.  
  753.  
  754. procedure Info (var TwoPlayer : boolean);
  755. var response : char;
  756. begin
  757. repeat
  758.  OutString (33, 12, 'How many players?');
  759.  OutString (37, 13, '(');
  760.  TextColor (lightred);
  761.  OutString (38, 13, '1 ');
  762.  TextColor (white);
  763.  OutString (40, 13, 'or ');
  764.  TextColor (lightred);
  765.  OutString (43, 13, '2');
  766.  TextColor (white);
  767.  OutString (44, 13,  ')');
  768.  GotoXY (40, 14);
  769.  readln (response);
  770.  until ((response = '1') OR (response = '2'));
  771.    if response = '1' then
  772.       TwoPlayer := FALSE
  773.    else
  774.       TwoPlayer := TRUE;
  775.  
  776. end;
  777.  
  778. procedure TitleScreen (var TwoPlayer:boolean);
  779.  
  780. var response: char;
  781.  
  782. Begin
  783. TextBackground (black);
  784. clrscr;
  785. TextBackground (black);
  786. DrawTitleBox;
  787. Title;
  788. Info (TwoPlayer);
  789. TextBackground (black);
  790. TextColor (white);
  791. End; {procedure TitleScreen}
  792.  
  793. {___________________________________________________________________
  794. |  DrawFrame
  795. |     One of the procedures involving the interface.
  796. |     This procedure draws the ascii graphical skeleton of the
  797. |     screen.  It also takes into account the turn in its choice of
  798. |     colors.
  799. |__________________________________________________________________}
  800.  
  801. procedure DrawFrame (ComputerTurn: boolean);
  802.  
  803. var Row: integer;
  804.     Column: integer;
  805.  
  806. begin
  807.    {Clear screen with Black background.}
  808.    TextBackGround (BLACK);
  809.    TextColor (BLACK);
  810.    For Row:= 1 to 25 do
  811.       For Column := 1 to 80 do begin
  812.          if NOT ((Row = 25) and (Column = 80)) then
  813.             OutString (Column, Row, chr(219));
  814.       end; {for column}
  815.    if ComputerTurn = TRUE then
  816.       ColorDim
  817.    else
  818.       ColorFrame;
  819.    OutString (1,1,chr(201));
  820.    OutString (1,24,chr(200));
  821.    OutString (31,1,chr(203));
  822.    OutString (31,24,chr(202));
  823.    for Column := 2 to 30 do begin
  824.       OutString (Column,1,chr(205));
  825.       OutString (Column,24,chr(205));
  826.    end; {for}
  827.    For Row := 2 to 23 do begin
  828.       OutString (1,Row,chr(186));
  829.       OutString (31,Row,chr(186));
  830.    end; {for}
  831.    Outstring (1,18,chr(204));
  832.    Outstring (31,18,chr(185));
  833.    For Row := 2 to 30 do
  834.       OutString (Row,18,chr(205));
  835.    OutString (31,5,chr(204));
  836.    OutString (31,13,chr(204));
  837.    if ComputerTurn = TRUE then
  838.       ColorFrame
  839.    else
  840.       ColorDim;
  841.    For Column := 51 to 79 do begin
  842.       OutString (Column,1,chr(205));
  843.       OutString (Column,18,chr(205));
  844.       OutString (Column,24,chr(205));
  845.    end; {for}
  846.    For Row := 2 to 23 do begin
  847.       OutString (50,Row,chr(186));
  848.       OutString (80,Row,chr(186));
  849.    end; {for}
  850.    OutString (50,1,chr(203));
  851.    OutString (50,24,chr(202));
  852.    OutString (50,5,chr(185));
  853.    OutString (50,13,chr(185));
  854.    OutString (50,18,chr(204));
  855.    OutString (80,1,chr(187));
  856.    OutString (80,24,chr(188));
  857.    ColorFrame;
  858.    For Column := 32 to 49 do begin
  859.       OutString (Column,1,chr(205));
  860.       OutString (Column,5,chr(205));
  861.       OutString (Column,13,chr(205));
  862.       OutString (Column,24,chr(205));
  863.    end; {for}
  864.  
  865.    TextColor (BLUE);
  866.    for Row := 2 to 4 do
  867.       for Column := 32 to 49 do
  868.          OutString (Column,Row,chr(219));
  869.    TextColor (WHITE);
  870.    TextBackground (BLUE);
  871.    OutString (34,2,'Spite & Malice');
  872.    OutString (34,3,'By Ben Arnoldy');
  873.    OutString (34,4,'& Raechel Kula');
  874. end; {procedure DrawFrame}
  875.  
  876. {___________________________________________________________________
  877. |  DrawDiscards
  878. |     One of the procedures involved with the interface.
  879. |     This procedure sets up the discard portions of the screen.
  880. |__________________________________________________________________}
  881.  
  882. procedure DrawDiscards (ComputerTurn:boolean);
  883.  
  884. var Counter: Pos_t;
  885.  
  886. begin
  887.  
  888.    if ComputerTurn = TRUE then
  889.       ColorDim
  890.    else
  891.       ColorNormalText;
  892.    OutString (9,2,'Player Discard');
  893.    if ComputerTurn = TRUE then
  894.       ColorNormalText
  895.    else
  896.       ColorDim;
  897.    if (TwoPlayer = FALSE) then
  898.       OutString (58,2,'Computer Discard')
  899.    else if (TwoPlayer = TRUE) then
  900.       OutString (58,2,'Opponent Discard');
  901.    ColorPosition;
  902.    OutString (3,3,'H'+chr(26));
  903.    OutString (10,3,'I'+chr(26));
  904.    OutString (17,3,'J'+chr(26));
  905.    OutString (24,3,'K'+chr(26));
  906.    OutString (52,3,'P'+chr(26));
  907.    OutString (59,3,'Q'+chr(26));
  908.    OutString (66,3,'R'+chr(26));
  909.    OutString (73,3,'S'+chr(26));
  910.    for Counter := 1 to 14 do begin
  911.       if ComputerTurn = TRUE then
  912.          ColorDim
  913.       else
  914.          ColorCard;
  915.       OutString(6,2+Counter,
  916.          CardString (PlayerDiscardPile1.SeeRandom(Counter)));
  917.       OutString(13,2+Counter,
  918.          CardString (PlayerDiscardPile2.SeeRandom(Counter)));
  919.       OutString(20, 2+Counter,
  920.          CardString (PlayerDiscardPile3.SeeRandom(Counter)));
  921.       OutString(27, 2+Counter,
  922.          CardString (PlayerDiscardPile4.SeeRandom(Counter)));
  923.       if ComputerTurn = FALSE then
  924.          ColorDim
  925.       else
  926.          ColorCard;
  927.       OutString(55, 2+Counter,
  928.          CardString (ComputerDiscardPile1.SeeRandom(Counter)));
  929.       OutString(62, 2+Counter,
  930.          CardString (ComputerDiscardPile2.SeeRandom(Counter)));
  931.       OutString(69, 2+Counter,
  932.          CardString (ComputerDiscardPile3.SeeRandom(Counter)));
  933.       OutString(76, 2+Counter,
  934.          CardString (ComputerDiscardPile4.SeeRandom(Counter)));
  935.    end; {for}
  936.    {if there are too many cards in a discard pile to display...}
  937.    TextColor (LIGHTred);
  938.    TextBackground (BLACK);
  939.    for Counter := 1 to 4 do begin
  940.       if PosTable [7+Counter]^.NumCards > 14 then
  941.          OutString ((-2 + (Counter*7)),17,'more');
  942.       if PosTable [15+Counter]^.NumCards > 14 then
  943.          OutString ((44 + (Counter*7)),17,'more');
  944.    end; {for}
  945. end; {procedure DrawDiscards}
  946.  
  947. {___________________________________________________________________
  948. |  DrawHands
  949. |     One of the procedures involved with the interface.
  950. |     This procedure displays the hands and scorepiles.
  951. |__________________________________________________________________}
  952.  
  953. procedure DrawHands (ComputerTurn:boolean);
  954.  
  955. var CardFace: string;
  956.  
  957. begin
  958.  
  959.    if ComputerTurn = TRUE then
  960.       ColorDim
  961.    else
  962.       ColorNormalText;
  963.    GotoXY (2,19);
  964.    write ('Player''s Hand:');
  965.    if ComputerTurn = FALSE then
  966.       ColorDim
  967.    else
  968.       ColorNormalText;
  969.    if (TwoPlayer = FALSE) then begin
  970.       GotoXY (51,19);
  971.       write ('Computer''s Hand:');
  972.    end
  973.    else if (TwoPlayer = TRUE) then begin
  974.       GotoXY (51,19);
  975.       write ('Opponent''s Hand:');
  976.    end;
  977.    ColorPosition;
  978.    OutString (3,21,'A'+chr(24));
  979.    OutString (8,21,'B'+chr(24));
  980.    OutString (13,21,'C'+chr(24));
  981.    OutString (18,21,'D'+chr(24));
  982.    OutString (23,21,'E'+chr(24));
  983.    OutString (28,21,'F'+chr(24));
  984.    OutString (52,21,'T'+chr(24));
  985.    OutString (57,21,'U'+chr(24));
  986.    OutString (62,21,'V'+chr(24));
  987.    OutString (67,21,'W'+chr(24));
  988.    OutString (72,21,'X'+chr(24));
  989.    OutString (77,21,'Y'+chr(24));
  990.    If ComputerTurn = TRUE then
  991.       ColorDim
  992.    else
  993.       ColorCard;
  994.    OutString(3,20,CardString (PlayerHand.SeeRandom(1)));
  995.    OutString(8,20,CardString (PlayerHand.SeeRandom(2)));
  996.    OutString(13,20,CardString (PlayerHand.SeeRandom(3)));
  997.    OutString(18,20,CardString (PlayerHand.SeeRandom(4)));
  998.    OutString(23,20,CardString (PlayerHand.SeeRandom(5)));
  999.    OutString(28,20,CardString (PlayerHand.SeeRandom(6)));
  1000.    If ComputerTurn = FALSE then
  1001.       ColorDim
  1002.    else
  1003.       ColorCard;
  1004.    If TwoPlayer then begin
  1005.       OutString(52,20,CardString (ComputerHand.SeeRandom(1)));
  1006.       OutString(57,20,CardString (ComputerHand.SeeRandom(2)));
  1007.       OutString(62,20,CardString (ComputerHand.SeeRandom(3)));
  1008.       OutString(67,20,CardString (ComputerHand.SeeRandom(4)));
  1009.       OutString(72,20,CardString (ComputerHand.SeeRandom(5)));
  1010.       OutString(77,20,CardString (ComputerHand.SeeRandom(6)));
  1011.    end {if}
  1012.    else begin
  1013.       CardFace := chr(168) + chr(63);
  1014.       if ComputerHand.NumCards > 0 then
  1015.          OutString(52,20,CardFace);
  1016.       if ComputerHand.NumCards > 1 then
  1017.          OutString(57,20,CardFace);
  1018.       if ComputerHand.NumCards > 2 then
  1019.          OutString(62,20,CardFace);
  1020.       if ComputerHand.NumCards > 3 then
  1021.          OutString(67,20,CardFace);
  1022.       if ComputerHand.NumCards > 4 then
  1023.          OutString(72,20,CardFace);
  1024.       if ComputerHand.NumCards > 5 then
  1025.          OutString(77,20,CardFace);
  1026.    end; {if-else}
  1027.    if ComputerTurn = TRUE then
  1028.       ColorDim
  1029.    else
  1030.       ColorNormalText;
  1031.    GotoXY (2,23);
  1032.    write ('Score Pile: ', PlayerScorePile.NumCards,
  1033.       ' cards> ');
  1034.    ColorPosition;
  1035.    write('G'+chr(26));
  1036.    TextColor (BLACK);
  1037.    TextBackground (BLACK);
  1038.    write(' ');
  1039.    if ComputerTurn = TRUE then
  1040.       ColorDim
  1041.    else
  1042.       ColorCard;
  1043.    write (CardString (PlayerScorePile.SeeRandom(1)));
  1044.    if ComputerTurn = FALSE then
  1045.       ColorDim
  1046.    else
  1047.       ColorNormalText;
  1048.    GotoXY (51,23);
  1049.    write ('Score Pile: ', ComputerScorePile.NumCards,
  1050.       ' cards> ');
  1051.    ColorPosition;
  1052.    write('Z'+chr(26));
  1053.    TextColor (BLACK);
  1054.    TextBackground (BLACK);
  1055.    write(' ');
  1056.    if ComputerTurn = FALSE then
  1057.       ColorDim
  1058.    else
  1059.       ColorCard;
  1060.    write (CardString (ComputerScorePile.SeeRandom(1)));
  1061. end; {procedure DrawHands}
  1062.  
  1063. {___________________________________________________________________
  1064. |  DrawAcePiles
  1065. |     One of the procedures involved with the interface.
  1066. |     This procedure draws the AcePile portion of the screen.
  1067. |__________________________________________________________________}
  1068.  
  1069. procedure DrawAcePiles;
  1070.  
  1071. var Counter: integer;
  1072.  
  1073. begin
  1074.  
  1075.    ColorNormalText;
  1076.    OutString (36,5,'Ace Piles:');
  1077.    ColorPosition;
  1078.    OutString (38,8,'L'+chr(26));
  1079.    OutString (38,9,'M'+chr(26));
  1080.    OutString (38,10,'N'+chr(26));
  1081.    OutString (38,11,'O'+chr(26));
  1082.    ColorCard;
  1083.    for Counter := 1 to 4 do begin
  1084.       OutString(41,7+Counter,CardString (TopCardTable [11+Counter] ));
  1085.       if CardValue( TopCardTable [11+Counter] )=0 then
  1086.          if AceTopCard (11+Counter) < 10 then
  1087.             OutString(45,7+Counter,chr(AceTopCard (11+Counter) + 48))
  1088.          else if AceTopCard (11+Counter) = 10 then
  1089.             OutString(45,7+Counter,'10')
  1090.          else if AceTopCard (11+Counter) = 11 then
  1091.             OutString(45,7+Counter,'JA')
  1092.          else if AceTopCard (11+Counter) = 12 then
  1093.             OutString(45,7+Counter,'QU')
  1094.          else if AceTopCard (11+Counter) = 13 then
  1095.             OutString(45,7+Counter,'KI');
  1096.    end; {for}
  1097. end; {Display}
  1098.  
  1099. {___________________________________________________________________
  1100. |  DrawMessageBox
  1101. |     One of the procedures involved with the interface.
  1102. |     This procedure clears the message portion of the screen and
  1103. |     prints a message displaying the turn.
  1104. |__________________________________________________________________}
  1105.  
  1106. procedure DrawMessageBox (ComputerTurn: boolean);
  1107.  
  1108. var
  1109.    Column: integer;
  1110.    Row: integer;
  1111.  
  1112. begin
  1113.  
  1114.    TextColor (BLACK);
  1115.    TextBackground (BLACK);
  1116.    for Column := 32 to 49 do
  1117.       for Row := 14 to 23 do
  1118.          OutString (Column,Row,chr(219));
  1119.    ColorNormalText;
  1120.    if ((ComputerTurn = TRUE) AND (TwoPlayer = FALSE)) then begin
  1121.       GotoXY (33,15);
  1122.       write ('Computer''s Turn');
  1123.    end
  1124.    else if ((ComputerTurn = TRUE) AND (TwoPlayer = TRUE)) then begin
  1125.       GotoXY (33,15);
  1126.       write ('Opponent''s Turn');
  1127.    end
  1128.    else begin
  1129.       GotoXY (34,15);
  1130.       write ('Player''s Turn');
  1131.    end;
  1132. end; {procedure DrawMessageBox}
  1133.  
  1134. {___________________________________________________________________
  1135. |  Display
  1136. |     This procedure directs the interface procedures for a complete
  1137. |     redrawing of the screen.
  1138. |__________________________________________________________________}
  1139.  
  1140. procedure Display;
  1141.  
  1142. begin
  1143.    clrscr;
  1144.    DrawFrame (ComputerTurn);
  1145.    DrawDiscards (ComputerTurn);
  1146.    DrawHands (ComputerTurn);
  1147.    DrawAcePiles;
  1148.    DrawMessageBox (ComputerTurn);
  1149. end; {Display}
  1150.  
  1151. {___________________________________________________________________
  1152. |  PickUpHand
  1153. |     Picks up the required number of cards from the draw pile and
  1154. |     places them in the hand of the person whose turn it is.
  1155. |     This procedure also checks to see if the draw pile has run out
  1156. |     of cards.  If so the trash pile is placed in the draw pile and
  1157. |     the draw pile is subsequently reshuffled.
  1158. |___________________________________________________________________}
  1159.  
  1160. Procedure PickupHand (var Hand : pile);
  1161.  
  1162. var numToGet, count, Counter : integer;
  1163.  
  1164. begin
  1165.  
  1166.    If (Hand.NumCards > 3)Then
  1167.       numToGet := 1
  1168.    Else
  1169.       numToGet := (5 - Hand.NumCards);
  1170.  
  1171.    For count := 1 to numToGet Do begin
  1172.       If DrawPile.NumCards = 0 then begin {Draw pile out of card, replenish}
  1173.          For Counter := 1 to TrashPile.NumCards do
  1174.             DrawPile.PutOnTop (TrashPile.RemoveFromTop);
  1175.          DrawPile.RandomShuffle;
  1176.       end; {if}
  1177.       Hand.PutOnTop (DrawPile.RemoveFromTop);
  1178.    end; {for}
  1179. end; {procedure PickupHand}
  1180.  
  1181. {____________________________________________________________________
  1182. |  PickUpCards
  1183. |     Sends correct hand to the PickupHand procedure according to
  1184. |     whose turn it is.
  1185. |___________________________________________________________________}
  1186.  
  1187. Procedure PickupCards;
  1188.  
  1189. begin
  1190.    If ComputerTurn Then
  1191.       PickupHand (ComputerHand)
  1192.    Else
  1193.       PickupHand (PlayerHand);
  1194.  
  1195.    InitTable; {Refresh the Top Card Table}
  1196. end; {PickupCards}
  1197.  
  1198. {____________________________________________________________________
  1199. |  HouseKeeping
  1200. |     Performs some checks after a card has been moved.
  1201. |     These checks include: removing completed ace piles,
  1202. |        checking for completed game, and checking for
  1203. |        insufficient cards to discard.
  1204. |___________________________________________________________________}
  1205.  
  1206. procedure HouseKeeping;
  1207.  
  1208. var Counter: integer;
  1209.     Counter2: integer;
  1210.  
  1211. begin
  1212.  
  1213.    InitTable; {Keep current top card information updated.}
  1214.  
  1215.    {Clean up any full ace piles.}
  1216.  
  1217.    for Counter := 12 to 15 do
  1218.       if PosTable [Counter]^.NumCards = 13 then
  1219.          for Counter2 := 1 to 13 do
  1220.             TrashPile.PutOnTop (PosTable [Counter]^.RemoveFromTop);
  1221.  
  1222.    {Check for Game over.}
  1223.  
  1224.    if ComputerScorePile.NumCards = 0 then
  1225.       begin
  1226.          Game := FALSE;
  1227.          Discard := TRUE;
  1228.          Winner := 'Computer';
  1229.       end; {if}
  1230.  
  1231.    if PlayerScorePile.NumCards = 0 then
  1232.       begin
  1233.          Game := FALSE;
  1234.          Discard := TRUE;
  1235.          Winner := 'Player';
  1236.       end; {if}
  1237.  
  1238.    {Run out of cards before discard.}
  1239.  
  1240.    If ((Discard = FALSE) AND ComputerTurn AND
  1241.        (ComputerHand.NumCards = 0)) then
  1242.       PickUpCards;
  1243.    If ((Discard = FALSE) AND (NOT ComputerTurn) AND
  1244.        (PlayerHand.NumCards = 0)) then
  1245.       PickUpCards;
  1246.  
  1247. end; {procedure HouseKeeping}
  1248.  
  1249. {____________________________________________________________________
  1250. |  MoveCard
  1251. |     Moves a card from one pile to another as specified.
  1252. |___________________________________________________________________}
  1253.  
  1254. Procedure MoveCard (From, Tto : integer);
  1255.  
  1256. var frompile : pilepointer_t;  value: CardVal_t;
  1257.     dummy: integer;
  1258.  
  1259. begin
  1260.   if ((From < 7) Or ((From > 19) AND (From < 26))) then begin
  1261.      frompile :=PosTable[From];
  1262.      value := TopCardTable[From];
  1263.      dummy := frompile^.DeleteByValue(value);
  1264.      PosTable[Tto]^.PutOnTop(value);
  1265.      end
  1266.   else
  1267.      PosTable[Tto]^.PutOnTop (PosTable[From]^.RemoveFromTop);
  1268.  
  1269.   HouseKeeping; {Calls the HouseKeeping procedure}
  1270. end; {procedure MoveCard}
  1271.  
  1272. {____________________________________________________________________
  1273. |  WhoseTurn
  1274. |     This procedure changes the turns.
  1275. |___________________________________________________________________}
  1276.  
  1277. Procedure WhoseTurn (var ComputerTurn : boolean);
  1278.  
  1279. begin
  1280.    If ComputerTurn Then
  1281.       ComputerTurn := False
  1282.    Else
  1283.       ComputerTurn := True;
  1284. end; {WhoseTurn}
  1285.  
  1286. {____________________________________________________________________
  1287. |  CheckMove
  1288. |     Checks to see if the move proposed is a) valid, and
  1289. |       b) a discard.
  1290. |___________________________________________________________________}
  1291.  
  1292. Procedure CheckMove(var From, Tto: integer);
  1293.  
  1294. var
  1295.    TopCard: integer;
  1296.    position: Pos_t;
  1297.    Counter: Pos_t;
  1298.    EmptyAcePile: boolean;
  1299.  
  1300. begin
  1301.    InitTable;
  1302.    Valid := TRUE;
  1303.    Discard := FALSE;
  1304.    MustMove := FALSE;
  1305.  
  1306.  
  1307.    If TopCardTable [From] = NULL then
  1308.       Valid := FALSE; {Invalid if moving from empty space.}
  1309.    If (Valid AND ((Tto < 8) OR (Tto > 19))) then
  1310.       Valid := FALSE;{Invalid if proposed to move card to ScorePiles or Hands}
  1311.    If (Valid AND ComputerTurn AND ((Tto < 12) OR (From < 12))) then
  1312.       Valid := FALSE; {Invalid if computer proposed to or from player's side.}
  1313.    If (VALID AND (NOT ComputerTurn) AND ((Tto > 15) OR (From > 15))) then
  1314.       Valid := FALSE; {Invalid if player proposed to or from computer's side.}
  1315.    If (VALID AND ((From > 11) AND (From < 16))) then
  1316.       Valid := FALSE; {Invalid if to Acepile from Acepile.}
  1317.    if (VALID AND (((Tto > 7) AND (Tto < 12)) OR ((Tto > 15) AND (Tto < 20)))
  1318.       AND (((From < 12) AND (From > 6)) OR ((From = 26) OR
  1319.       ((From > 15) AND (From < 20))))) then
  1320.       Valid := FALSE; {Invalid if to discard from a discard or score pile.}
  1321.  
  1322.    {Ace on top of Discard Pile must be played first.}
  1323.  
  1324.    EmptyAcePile := FALSE;
  1325.    for Counter := 1 to 4 do
  1326.       if PosTable [Counter + 11]^.NumCards = 0 then
  1327.          EmptyAcePile := TRUE;
  1328.  
  1329.    if (EmptyAcePile AND Valid) then
  1330.       for Counter := 1 to 4 do begin
  1331.          if ((ComputerTurn) AND (CardValue (TopCardTable [Counter + 15]) = 1)
  1332.            AND (From <> (Counter + 15))
  1333.            AND (NOT(CardValue(TopCardTable[From])=1))) then
  1334.             Valid := FALSE;
  1335.          if ((NOT ComputerTurn) AND (CardValue (TopCardTable[Counter+7]) = 1)
  1336.            AND (From <> (Counter + 7))
  1337.            AND (NOT(CardValue(TopCardTable[From])=1))) then
  1338.            Valid := FALSE;
  1339.       end; {for}
  1340.  
  1341.    if (EmptyAcePile AND Valid) then
  1342.       for Counter := 1 to 4 do begin
  1343.          if ((ComputerTurn) AND (CardValue (TopCardTable [Counter + 15]) = 1)
  1344.            AND (From = (Counter + 15))
  1345.            OR (CardValue(TopCardTable[From])=1)) then begin
  1346.             Valid := True;
  1347.             MustMove := True;
  1348.          end; {if}
  1349.       end; {for} {forces computer to play ace when
  1350.                    To/From scores below threshold}
  1351.  
  1352.  
  1353.    {Ace Piles Check}
  1354.    if (VALID AND ((Tto > 11) AND (Tto < 16))) then begin
  1355.       TopCard := AceTopCard (Tto);
  1356.       If ((TopCard = NULL) AND (CardValue (TopCardTable [From]) <> 1)) then
  1357.          Valid := FALSE {If placing non-ace on empty ace pile.}
  1358.       else if TopCard = NULL then
  1359.          Valid := TRUE
  1360.       else if CardValue(TopCardTable[From]) = 0 then
  1361.          Valid := TRUE {In all cases but as ace, joker is valid.}
  1362.       else if ((TopCard + 1) <> CardValue (TopCardTable[From])) then
  1363.          Valid := FALSE; {If it is not next card in series.}
  1364.    end; {if}
  1365.  
  1366.    {Discard Check}
  1367.    if (Valid AND ((ComputerTurn AND ((Tto < 20) AND (Tto > 15) AND (From > 19)
  1368.       AND (From < 26))) OR (NOT ComputerTurn AND ((Tto < 12) AND (Tto > 7)
  1369.       AND (From < 7) AND (From > 0))))) then
  1370.       if PosTable [Tto]^.NumCards > 0 then begin
  1371.          Discard := TRUE;
  1372.          if ComputerTurn then
  1373.             For Counter := 16 to 19 do
  1374.                if PosTable [Counter]^.NumCards = 0 then begin
  1375.                   Valid := FALSE;
  1376.                   Discard := FALSE;
  1377.                end; {if}
  1378.          if NOT ComputerTurn then
  1379.             For Counter := 8 to 11 do
  1380.                if PosTable [Counter]^.NumCards = 0 then begin
  1381.                   Valid := FALSE;
  1382.                   Discard := FALSE;
  1383.                end; {if}
  1384.       end; {if}
  1385. end;{CheckMove}
  1386.  
  1387. {____________________________________________________________________
  1388. |  GetMove
  1389. |     Requested a proposal for a move from the player.
  1390. |___________________________________________________________________}
  1391.  
  1392. Procedure GetMove (var From, Tto: integer);
  1393.  
  1394. var FromChar, ToChar: char;
  1395.  
  1396. begin
  1397.    Display;
  1398.    ColorNormalText;
  1399.    OutString (33,17,'Enter positions');
  1400.    ColorDim;
  1401.    OutString (35,18,'(@ to Quit)');
  1402.    ColorNormalText;
  1403.    OutString (33,19,'Move a card');
  1404.    OutString (33,20,'from: ');
  1405.    readln (FromChar);
  1406.    OutString (33,21,'to: ');
  1407.    readln (ToChar);
  1408.    From := ord(UpCase(FromChar)) - 64;
  1409.    Tto := ord(UpCase(ToChar)) - 64;
  1410.  
  1411.    {-64 to adjust for alphabet's position in ASCII table.}
  1412.    if ((From = 0) OR (Tto = 0)) then begin {quit}
  1413.       ColorNormalText;
  1414.       clrscr;
  1415.       HALT;
  1416.    end; {if}
  1417.  
  1418.    if ((From < 1) OR (From > 26) OR (Tto < 1) OR (From > 26)) then begin
  1419.       From := 1;
  1420.       Tto := 1;
  1421.    end; {if}
  1422.  
  1423. end; {GetMove}
  1424.  
  1425. {____________________________________________________________________
  1426. |  ResultsofCheck
  1427. |     Displays a message regarding the results of the check in
  1428. |     CheckMove.
  1429. |___________________________________________________________________}
  1430.  
  1431. procedure ResultsofCheck;
  1432.  
  1433. begin
  1434.    DrawMessageBox (ComputerTurn);    {Calls the DrawMessageBox procedure}
  1435.    ColorNormalText;
  1436.    OutString (33,17,'Proposed Move:');
  1437.    GotoXY (33,18);
  1438.    write ('From: ',chr(From + 64));
  1439.    GotoXY (33,19);
  1440.    write ('To: ',chr(Tto + 64));
  1441.    GotoXY (33,21);
  1442.    if NOT Valid then begin
  1443.       TextColor (WHITE+BLINK);
  1444.       write ('Is NOT Valid!!');
  1445.    end
  1446.    else begin
  1447.       TextColor (WHITE);
  1448.       write ('Is Valid.');
  1449.    end; {if else}
  1450.    TextColor (RED+BLINK);
  1451.    OutString (33,23,'Press <Enter>...');
  1452.    readln;
  1453. end; {ResultsofCheck}
  1454.  
  1455. {_____________________________________________________________________
  1456. |    PlayAgainBox
  1457. |     Displays Box and asks player if he/she wants to play again
  1458. |_____________________________________________________________________}
  1459. procedure PlayAgainBox;
  1460.  
  1461. Begin
  1462.  ColorNormalText;
  1463.  clrscr;
  1464.  DrawTitleBox;
  1465.  ColorNormalText;
  1466.  OutString (27, 11, 'Would you like to play again?');
  1467.  OutString (37, 12, '(');
  1468.  TextColor (LightRed);
  1469.  OutString (38, 12,  'Y ');
  1470.  TextColor (white);
  1471.  OutString (40, 12, 'or ');
  1472.  TextColor (lightRed);
  1473.  OutString (43, 12, 'N');
  1474.  TextColor (white);
  1475.  OutString (44, 12, ')');
  1476. End;
  1477.  
  1478. {____________________________________________________________________
  1479. |  GameOverDisplay
  1480. |     Notifies player that the game is over, displays who won, and
  1481. |     asks the player if he/she would like to play again.
  1482. |___________________________________________________________________}
  1483.  
  1484. Procedure GameOverDisplay (Winner: string);
  1485.  
  1486. var Response: char;
  1487.     Valid: boolean;
  1488.  
  1489. begin
  1490.    ColorNormalText;
  1491.    clrscr;
  1492.    DrawTitleBox;
  1493.    ColorNormalText;
  1494.    OutString (36, 10, 'Game Over!!');
  1495.    OutString (32, 12, 'The ');
  1496.    OutString (36, 12, Winner);
  1497.    OutString (44, 12,  ' wins!');
  1498.    readln;
  1499.    {Play Again?}
  1500.    Valid := FALSE;
  1501.    Repeat
  1502.       PlayAgainBox;
  1503.       readln (Response);
  1504.       if (Upcase (Response) = 'Y') then begin
  1505.          AnotherGame := TRUE;
  1506.          Valid := TRUE;
  1507.       end
  1508.       else
  1509.       if (Upcase (Response) = 'N') then begin
  1510.          AnotherGame := FALSE;
  1511.          Valid := TRUE;
  1512.       end
  1513.       else
  1514.       Valid := FALSE;
  1515.    Until Valid;
  1516. end; {function AnotherGame}
  1517.  
  1518. {___________________________________________________________________
  1519. |  SetUp
  1520. |     One of Decision's evaluative functions.
  1521. |     This function adds a negative weight if a play will result in
  1522. |     setting up the player to play from his/her score pile.
  1523. |__________________________________________________________________}
  1524.  
  1525. Function SetUp: integer;
  1526.  
  1527. const
  1528.    WEIGHT = -20;
  1529.    SWEIGHT =-10;
  1530.  
  1531. var
  1532.    position: integer;
  1533.    Points: integer;
  1534.    CardCanPlay: integer;
  1535.    ScoreCard: integer;
  1536.    CardPlayed: integer;
  1537.  
  1538. begin
  1539.    Points := 0;
  1540.    ScoreCard := CardValue (TopCardTable [7]);
  1541.    CardPlayed := AceTopCard (Tto) + 1;
  1542.    CardCanPlay := CardPlayed + 1;
  1543.    If CardCanPlay  = ScoreCard then begin
  1544.       Points := WEIGHT;
  1545.       For position := 16 to 26 do begin
  1546.          if CardValue (TopCardTable [position]) = ScoreCard then
  1547.             Points := 0;
  1548.          if position = From then
  1549.             if CardValue (PosTable [position]^.SeeRandom(2)) = ScoreCard then
  1550.                Points := 0;
  1551.       end; {for}
  1552.    end; {if}
  1553.    If (Points = WEIGHT) AND (From = 26) then
  1554.     Points := SWEIGHT;
  1555.  
  1556.    SetUp := Points;
  1557. end; {function SetUp}
  1558.  
  1559. {___________________________________________________________________
  1560. |  Block
  1561. |    One of Decision's evaluative functions.
  1562. |    This function adds a positive weight if the play results in
  1563. |    preventing the player from playing from his score pile.
  1564. |__________________________________________________________________}
  1565.  
  1566. function Block: integer;
  1567.  
  1568. const
  1569.    WEIGHT = 25;
  1570.  
  1571. var
  1572.    Points: integer;
  1573.    ScoreCard: integer;
  1574.    CardPlayed: integer;
  1575.  
  1576. begin
  1577.    Points := 0;
  1578.    ScoreCard := CardValue (TopCardTable [7]);
  1579.    CardPlayed := AceTopCard (Tto) + 1;
  1580.    If CardPlayed = ScoreCard then
  1581.       Points := WEIGHT;
  1582.    Block := points;
  1583. end; {Block}
  1584.  
  1585. {___________________________________________________________________
  1586. |  PlayMore
  1587. |    One of Decision's evaluative functions.
  1588. |    This function adds a positive weight if a play results in the
  1589. |    computer being able to play more cards.
  1590. |    It also adds a positive weight if a play allows the computer to
  1591. |    move a card.
  1592. |___________________________________________________________________}
  1593.  
  1594. function PlayMore: integer;
  1595.  
  1596. const
  1597.    WEIGHT = 15;  {If move allows the computer to move more cards.}
  1598.    WEIGHT2 = 10; {If Computer can move a card.}
  1599. var
  1600.    position: integer;
  1601.    Points: integer;
  1602.    CardCanPlay: integer;
  1603.    CardPlayed: integer;
  1604.  
  1605. begin
  1606.    Points := WEIGHT2; {Just for being able to play a card.}
  1607.    CardPlayed := AceTopCard (Tto) + 1;
  1608.    CardCanPlay := CardPlayed + 1;
  1609.  
  1610.    position := 16;
  1611.    While (Position < 27) do begin
  1612.       if CardValue (TopCardTable [position]) = CardCanPlay then
  1613.          Points := WEIGHT;
  1614.       if position = From then
  1615.          if CardValue(PosTable [position]^.SeeRandom (2)) = CardCanPlay then
  1616.             Points := WEIGHT;
  1617.       position := position + 1;
  1618.    end; {While}
  1619.  
  1620.         {Special case for Jokers}
  1621.    If CardValue (TopCardTable [From]) = 0 then
  1622.       Points := Points - WEIGHT;
  1623.    PlayMore := Points;
  1624. end; {function PlayMore}
  1625.  
  1626. {____________________________________________________________________
  1627. |  MoreCards
  1628. |     One of Decision's evaluative functions
  1629. |     This function adds weight to a play that will result in the
  1630. |     computer being able to pick up more cards at the beginning of
  1631. |     its next turn.  Additional weight is given to a play that will
  1632. |     result in the computer being able to pick up 5 more cards this
  1633. |     turn.
  1634. |____________________________________________________________________}
  1635.  
  1636. function MoreCards: integer;
  1637.  
  1638. const WEIGHT = 10;
  1639.       WEIGHT2 = 20;
  1640.  
  1641. var HolestoFill: integer;
  1642.     Counter: integer;
  1643.     Points: integer;
  1644.  
  1645. begin
  1646.    Points := 0;
  1647.  
  1648.                {creates empty discard pile, ie a hole to fill}
  1649.    If ((From >15) AND (From <20) AND (PosTable [From]^.NumCards = 1) AND
  1650.        (NOT CardValue(TopCardTable [From]) = 0)) then
  1651.       Points := WEIGHT;
  1652.  
  1653.              {takes into account the holes}
  1654.    HolestoFill := 0;
  1655.    If ((From > 19) AND (From < 26 )) then begin
  1656.       Points := WEIGHT;
  1657.       For Counter := 16 to 19 do begin
  1658.          If PosTable [Counter]^.NumCards = 0 then
  1659.             HolestoFill := HolestoFill + 1;
  1660.       end; {for}
  1661.       If (ComputerHand.NumCards - HolestoFill) = 0 then
  1662.           Points := WEIGHT2;
  1663.  
  1664.                  {special case for Jokers}
  1665.       If CardValue (TopCardTable [From]) = 0 then
  1666.           Points := Points - WEIGHT;
  1667.    end; {if}
  1668.    MoreCards := Points;
  1669. end; {MoreCards}
  1670.  
  1671. {_____________________________________________________________________
  1672. |  HelpScore
  1673. |     One of Decision's evaluative functions
  1674. |     This function will add positive weight to a play that results
  1675. |     in the computer being able to play from its score pile.
  1676. |____________________________________________________________________}
  1677.  
  1678. function HelpScore: integer;
  1679.  
  1680. const WEIGHT = 30;
  1681.  
  1682. var ScoreCard: integer;
  1683.     CardPlayed: integer;
  1684.     CardCanPlay: integer;
  1685.     Points: integer;
  1686.  
  1687. begin
  1688.    Points := 0;
  1689.    ScoreCard := CardValue (TopCardTable [26]);
  1690.    CardPlayed := AceTopCard (Tto) + 1;
  1691.    CardCanPlay := CardPlayed + 1;
  1692.    If CardCanPlay  = ScoreCard then
  1693.       Points := WEIGHT;
  1694.    HelpScore := Points;
  1695. end; {function HelpScore}
  1696.  
  1697. {_____________________________________________________________________
  1698. |  Score
  1699. |     One of Decision's evaluative functions.
  1700. |     This function adds positive weight to a score pile play.
  1701. |____________________________________________________________________}
  1702.  
  1703. function Score: integer;
  1704.  
  1705. const WEIGHT = 60;
  1706.       WEIGHT2 = 10;
  1707.  
  1708. var ScoreCard: integer;
  1709.     position: integer;
  1710.     Points: integer;
  1711.  
  1712. Begin
  1713.  Points := 0;
  1714.  if From = 26 then begin
  1715.    ScoreCard := CardValue (TopCardTable [26]);
  1716.    if (((AceTopCard (Tto) + 1) = ScoreCard) OR (ScoreCard = 0)) then begin
  1717.          Points := WEIGHT;
  1718.          if ((ScoreCard + 1) = CardValue (TopCardTable [7])) then begin
  1719.             Points := WEIGHT2;
  1720.             position := 16;
  1721.             while (position < 26) do begin
  1722.                position := position + 1;
  1723.                if ((TopCardTable [position] = 0)  OR
  1724.                    (TopCardTable [position] = (ScoreCard +1))) then
  1725.                    Points := WEIGHT;
  1726.             end; {While}
  1727.          end; {if}
  1728.    end; {if}
  1729.  end; {if}
  1730.  Score := Points;
  1731. end; {function Score}
  1732.  
  1733. {_____________________________________________________________________
  1734. |  SameScore
  1735. |     One of DiscardDecision's evaluative functions
  1736. |     This function adds a negative weight to a discard
  1737. |     of a card that is the same value as the computer's score
  1738. |     pile.
  1739. |____________________________________________________________________}
  1740.  
  1741. function SameScore: integer;
  1742.  
  1743. const WEIGHT = -5;
  1744.       JWEIGHT = -20;
  1745.  
  1746. var Points: integer;
  1747.  
  1748. begin
  1749.    Points := 0;
  1750.    If (CardValue(TopCardTable[From]) = CardValue (TopCardTable[26])) then
  1751.       Points := WEIGHT;
  1752.  
  1753.              {special case for Jokers}
  1754.    If CardValue (TopCardTable[From]) = 0 then
  1755.       Points := JWEIGHT;
  1756.  
  1757.    SameScore := Points;
  1758. end; {function SameScore}
  1759.  
  1760. {_____________________________________________________________________
  1761. |  Order
  1762. |     One of DecisionDiscard's evaluative functions
  1763. |     This function uses weights to prioritize a discard to the closest
  1764. |     possible lower value in relation to the top cards of the discard
  1765. |     piles.
  1766. |____________________________________________________________________}
  1767.  
  1768. function Order: integer;
  1769.  
  1770. const WEIGHT1 = 20;
  1771.       WEIGHT2 = 11;
  1772.       WEIGHT3 = 4;
  1773.       WEIGHT4 = -5;
  1774.       JWEIGHT = -20;
  1775.  
  1776. var next: CardVal_t;
  1777.     Points: integer;
  1778.  
  1779. begin
  1780.  
  1781.    next := CardValue (TopCardTable [Tto]) - 1;
  1782.    if (CardValue (TopCardTable [From]) = next)
  1783.       then Points := WEIGHT1;
  1784.    if ((CardValue (TopCardTable [From]) + 1) = next)
  1785.       then Points := WEIGHT2;
  1786.    if ((CardValue (TopCardTable[From]) + 1) < next)
  1787.       then Points := WEIGHT3;
  1788.    if (CardValue (TopCardTable [From]) > next)
  1789.       then Points := WEIGHT4;
  1790.  
  1791.       {special case for Jokers}
  1792.    if CardValue (TopCardTable [From]) = 0 then
  1793.       Points := JWEIGHT;
  1794.  
  1795.    Order := Points;
  1796. end; {Order}
  1797.  
  1798. {_____________________________________________________________________
  1799. |  HighCard
  1800. |     One of DecisionDiscard's evaluative functions.
  1801. |        This function weights the possible cards to fill in a space
  1802. |        in the discard piles.  It adds most weight to the highest
  1803. |        valued card.
  1804. |____________________________________________________________________}
  1805.  
  1806. function HighCard: integer;
  1807.  
  1808. var count, Points: integer;
  1809.  
  1810. begin
  1811.    Points := 0;
  1812.    if ((PosTable [16]^.NumCards = 0) OR (PosTable [17]^.NumCards = 0) OR
  1813.       (PosTable [18]^.NumCards = 0) OR (PosTable [19]^.NumCards = 0)) then
  1814.       for count := 20 to 25 do
  1815.          if (CardValue(TopCardTable [From]) >
  1816.             CardValue (TopCardTable [count])) then
  1817.             Points := Points + 1;
  1818.    HighCard := Points * 2;
  1819. end; {function HighCard}
  1820.  
  1821. {_____________________________________________________________________
  1822. |  DiscardDecision
  1823. |     This procedure is responsible for applying the various weights
  1824. |     on to the decision surrounding the computer's discard.
  1825. |____________________________________________________________________}
  1826.  
  1827. Procedure DiscardDecision (var From, Tto: integer);
  1828.  
  1829. var max: integer;
  1830.     f, t: integer;
  1831.  
  1832. Begin
  1833.  
  1834.    For f := 20 to 25 Do
  1835.       For t := 16 to 19 Do begin
  1836.          From := f;
  1837.          Tto := t;
  1838.       CheckMove (From, Tto);
  1839.       If Not (Valid) Then
  1840.          ChoiceRate[f, t] := -10000
  1841.       Else
  1842.          ChoiceRate[f, t] := ((HighCard) + (Order) + (SameScore));
  1843.       end; {for}
  1844.  
  1845.    From := 20;
  1846.    Tto := 16;
  1847.    max := 0;
  1848.    For f := 20 to 25 Do
  1849.       For t := 16 to 19 Do  begin
  1850.          If (ChoiceRate[f, t] > ChoiceRate[From, Tto]) Then  begin
  1851.             max := ChoiceRate[f, t];
  1852.             From := f;
  1853.             Tto := t;
  1854.          end; {if}
  1855.       end; {for}
  1856. End; {DiscardDecision}
  1857.  
  1858. {_____________________________________________________________________
  1859. |  Decision
  1860. |     This procedure is responsible for applying the weights to the
  1861. |     decision surrounding the computer's choice of moves.
  1862. |____________________________________________________________________}
  1863.  
  1864. Procedure Decision (var From, Tto: integer);
  1865.  
  1866. const Threshold = 10;
  1867.  
  1868. var Max: integer;
  1869.     f, t: integer;
  1870. Begin
  1871.    Display;
  1872.    For f := 1 to 26 do
  1873.       For t := 1 to 19 do
  1874.          ChoiceRate [f, t] := 0;
  1875.  
  1876.    For f := 16 to 26 Do
  1877.       For t := 12 to 15 Do begin
  1878.          From := f;
  1879.          Tto := t;
  1880.          CheckMove(From, Tto);
  1881.          If Not (Valid) Then
  1882.             ChoiceRate[f, t] := -10000
  1883.          Else
  1884.             ChoiceRate[f, t] := ((SetUp) + (Block) +
  1885.             (PlayMore) + (MoreCards) + (HelpScore) + (Score));
  1886.    end; {for}
  1887.  
  1888.    {Tests Threshold}
  1889.    From := 16;
  1890.    Tto := 12;
  1891.    max := 0;
  1892.    For f := 16 to 26 Do
  1893.       For t := 12 to 15 Do  begin
  1894.          If (ChoiceRate[f, t] > ChoiceRate[From, Tto]) Then  begin
  1895.             max := ChoiceRate[f, t];
  1896.             From := f;
  1897.             Tto := t;
  1898.          end; {if}
  1899.       end; {for}
  1900.    If (Max < Threshold) AND (NOT(MustMove)) Then
  1901.       DiscardDecision (From, Tto);
  1902.  
  1903. End; {Decision}
  1904.  
  1905. {============================================================================
  1906.                                  MAIN PROGRAM
  1907. ============================================================================}
  1908.  
  1909.  
  1910. BEGIN {Main Program}
  1911.    Repeat
  1912.       TitleScreen (TwoPlayer);
  1913.       Initialize;
  1914.       Deal;
  1915.       While (Game) Do begin
  1916.             WhoseTurn (ComputerTurn);
  1917.             PickupCards;
  1918.             Repeat
  1919.                   If ((ComputerTurn) AND (NOT TwoPlayer)) Then
  1920.                       Decision (From, Tto)
  1921.                   Else
  1922.                       GetMove (From, Tto);
  1923.                   CheckMove(From, Tto);
  1924.                   ResultsofCheck;
  1925.                   If Valid then
  1926.                      MoveCard (From, Tto);
  1927.             Until (Discard);
  1928.       End; {While Loop}
  1929.       GameOverDisplay (Winner);
  1930.    Until (NOT AnotherGame);
  1931. END. {Main Program}
  1932.  
  1933.  
  1934.